package com.example.pungolo.journal.model;

import java.util.Calendar;
import java.util.Date;

import com.example.pungolo.journal.U;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class DiaryDatabase {
  private SQLiteDatabase db;
  private int pageCount;
  private DiaryPage first;
  
  protected DiaryDatabase(SQLiteDatabase db) {
    this.db = db;
    refreshPagesCount();
  }
  
  protected void closeDb() {
    db.close();
  }
  
  public int getPageCount() {
    return pageCount;
  }
  
  public DiaryPage getDiaryPageAtIndex(int id) {
    Cursor qresult = db.rawQuery("SELECT * FROM pages ORDER BY day DESC LIMIT 1 OFFSET " + id, null);
    qresult.moveToFirst();
    DiaryPage res = null;
    if (qresult.getCount() > 0) {
      res = new DiaryPage();
      res.day = qresult.getInt(0);
      res.imagePath = qresult.getString(1);
      res.crop[0] = qresult.getInt(2);
      res.crop[1] = qresult.getInt(3);
      res.crop[2] = qresult.getInt(4);
      res.crop[3] = qresult.getInt(5);
      fetchEntriesForDiaryPage(res);
    }
    qresult.close();
    return res;
  }

  public DiaryPage getDiaryPageFromDate(Date day) {
    int dayAsInt = U.dayFromDate(day);
    return getDiaryPageFromDay(dayAsInt);
  }

  public DiaryPage getDiaryPageFromDay(int dayAsInt) {
    Cursor qresult = db.query(false, "pages", null, "day = " + dayAsInt, null, null, null, null, "1");
    DiaryPage res = null;
    if (qresult != null && qresult.getCount() > 0) {
      qresult.moveToFirst();
      res = new DiaryPage();
      res.day = dayAsInt;
      res.imagePath = qresult.getString(1);
      res.crop[0] = qresult.getInt(2);
      res.crop[1] = qresult.getInt(3);
      res.crop[2] = qresult.getInt(4);
      res.crop[3] = qresult.getInt(5);
      fetchEntriesForDiaryPage(res);
    }
    qresult.close();
    return res;
  }
  
  public DiaryEntry getDiaryEntryFromDateTime(Date datetime) {
    long key = datetime.getTime() / 1000;
    Cursor qresult = db.query(false, "entries", null, "datetime = " + key, null, null, null, null, "1");
    DiaryEntry res = null;
    if (qresult != null && qresult.getCount() > 0) {
      qresult.moveToFirst();
      res = new DiaryEntry();
      res.date = datetime;
      res.text = qresult.getString(1);
      res.mood = Mood.getMoodFromId(qresult.getInt(2));
    }
    qresult.close();
    return res;
  }
  
  private void fetchEntriesForDiaryPage(DiaryPage res) {
    long d0 = U.tsOfDayStart(res.day)   / 1000;
    long d1 = U.tsOfDayStart(res.day+1) / 1000;
    Cursor qresult = db.query(false, "entries", null,
        "datetime < " + d1 + " AND datetime > " + d0,
        null, null, null, "datetime ASC", null);
    if (qresult != null && qresult.getCount() > 0) {
      qresult.moveToFirst();
      while(!qresult.isAfterLast()) {
        DiaryEntry de = new DiaryEntry();
        de.date = new Date(qresult.getLong(0) * 1000);
        de.text = qresult.getString(1);
        de.mood = Mood.getMoodFromId(qresult.getInt(2));
        res.entries.add(de);
        qresult.moveToNext();
      }
    }
    qresult.close();
  }
  
  public void saveDiaryEntry(DiaryEntry d) {
    ContentValues v = new ContentValues();
    v.put("datetime", d.date.getTime() / 1000);
    v.put("text", d.text);
    v.put("mood", d.mood.id);
    db.replace("entries", null, v);
  }
  
  public boolean deleteDiaryEntry(DiaryEntry diaryEntry) {
    boolean success = false;
    
    db.beginTransaction();
    try {
      String key = Long.toString(diaryEntry.date.getTime() / 1000);
      success = db.delete("entries", "datetime = ?", new String[] { key }) == 1;
      if (success)
        db.setTransactionSuccessful();
    } catch (Exception e) {
      Log.e("pungolo-journal", e.getMessage());
    } finally {
      db.endTransaction();
    }
    
    return success;
  }

  public void saveDiaryPage(DiaryPage page) {
    db.beginTransaction();
    try {
      int day = page.day;
      String image = page.imagePath;
      int[] cropData = page.crop;
      ContentValues v = new ContentValues();
      v.put("day", day);
      v.put("image", image);
      v.put("cropl", cropData[0]);
      v.put("cropt", cropData[1]);
      v.put("cropr", cropData[2]);
      v.put("cropb", cropData[3]);
      // questo � un insert or update
      db.replace("pages", null, v);
      for (DiaryEntry d : page.entries) {
        saveDiaryEntry(d);
      }
      
      db.setTransactionSuccessful();
    } finally {
      db.endTransaction();
    }
    refreshPagesCount();
  }
  
  public boolean deleteDiaryPage(DiaryPage page) {
    boolean success = false;
    int deletes = 0;
    int toDelete = page.getEntryCount() + 1;
    
    db.beginTransaction();
    try {
      for (DiaryEntry d : page.entries) {
        deletes += deleteDiaryEntry(d) ? 1 : 0;
      }

      String key = Integer.toString(page.day);
      deletes += db.delete("pages", "day = ?", new String[] { key });
      U.delete(page.imagePath);
      
      success = deletes == toDelete;
      if (success)
        db.setTransactionSuccessful();
    } catch (Exception e) {
      Log.e("pungolo-journal", e.getMessage());
    } finally {
      db.endTransaction();
    }
    
    if (success)
      refreshPagesCount();
    return success;
  }
  
  private boolean createToday() {
    Date now = Calendar.getInstance().getTime();
    first = getDiaryPageFromDate(now);
    if (first == null) {
      // non c'� la pagina di oggi, creala
      first = new DiaryPage();
      first.day = U.dayFromDate(now);
      saveDiaryPage(first);
      return true;
    }
    return false;
  }
  
  public void refreshPagesCount() {
    createToday();
    Cursor c = db.rawQuery("select count(*) from pages", null);
    c.moveToFirst();
    pageCount = c.getInt(0);
    c.close();
  }

  public void getDaysFromMonth(int firstDay, boolean[] pages) {
    int lastDay = firstDay + 31;
    Cursor qresult = db.query(false, "pages", new String[] { "day" }, "day >= " + firstDay + " AND day < " + lastDay, null, null, null, null, null);
    if (qresult != null && qresult.getCount() > 0) {
      qresult.moveToFirst();
      while (!qresult.isAfterLast()) {
        int day = qresult.getInt(0);
        pages[day-firstDay] = true;
        qresult.moveToNext();
      }
    }
    qresult.close();
  }

  public int getIndexOfDay(int day) {
    Cursor c = db.rawQuery("select count(*) from pages where day > "+day, null);
    c.moveToFirst();
    int index = c.getInt(0);
    c.close();
    return index;
  }
}
